package com.gzhryc.shared_device.oem.micro.api.controllers.xcx.v1.member;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.alipay.api.response.AlipayTradeCreateResponse;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.api.DefaultAPIResponse;
import com.gzhryc.common.config.DefaultEnum;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.pay.adaptation.alipay.AlipayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.WXPayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalPayResponse;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.enums.EPayState;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.common.payment.dao.db.AlipayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.PayAccountGroup;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayConfig;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.models.CashWithdrawalConfig;
import com.gzhryc.shared_device.common.payment.services.AlipayOrderService;
import com.gzhryc.shared_device.common.payment.services.PayAccountGroupService;
import com.gzhryc.shared_device.common.payment.services.WXPayConfigService;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.LoginMember;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberRechargeOrder;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberTransferMoneyOrder;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberWallet;
import com.gzhryc.shared_device.oem.code.member.dao.enums.MemberRechargeOrderEnum;
import com.gzhryc.shared_device.oem.code.member.services.MemberRechargeOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberTransferMoneyOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberWalletService;
import com.gzhryc.shared_device.oem.code.member.services.dto.MemberTransferMoneyOrderSearch;
import com.gzhryc.shared_device.oem.code.order.CacheOrderCollect;
import com.gzhryc.shared_device.oem.micro.api.MicroConstants;
import com.gzhryc.shared_device.oem.micro.api.OrderCollectManager;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.ClientAPICodeConstants;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.PayResultCode;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberTransferMoneyApplyRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberTransferMoneyOrderInfoRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberTransferMoneyOrderInfoResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberTransferMoneyOrderListRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberTransferMoneyOrderListResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletInfoRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletInfoResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletRechargeRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletRechargeResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletRechargeResultRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.member.MemberWalletRechargeResultResponse;

public class MemberWalletController {

    static Logger log = Logger.getLogger(MemberWalletController.class);

    @Route(value = { "/xcx/v1/member/wallet/get.do" }, method = "POST")
    public MemberWalletInfoResponse wallet(HttpServletRequest request) {
        MemberWalletInfoResponse apiResp = new MemberWalletInfoResponse(ClientAPICodeConstants.NULL_DATA, "未找到钱包信息");
        MemberWalletInfoRequest apiReq = WebUtils.getJsonRequest(request, MemberWalletInfoRequest.class);
        if (apiReq != null && apiReq.getBody().getMemberId() != null) {
            LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
            if(!member.getId().equals(apiReq.getBody().getMemberId())){
                apiResp.setMsg("你是谁？");
                return apiResp;
            }

            MemberWallet wallet = MemberWalletService.self().getByMemberId(member.getId());
            if(wallet != null){
                apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                apiResp.getBody().setMoney(wallet.getMoneyStr());
                apiResp.getBody().setFreezeMoney(wallet.getFreezeMoneyStr());
                apiResp.getBody().setVirtualMoney(wallet.getVirtualMoney());              
                apiResp.getBody().setTransferState(1);

                WXPayConfig payConfig = WXPayConfigService.self().getByAppId(member.getAppId());
                if(payConfig == null || payConfig.getAccountGroupId() == null){
                    apiResp.getBody().setTransferState(2);
                }else {
                    PayAccountGroup payAccountGroup = PayAccountGroupService.self().getById(payConfig.getAccountGroupId());
                    if (payAccountGroup == null || !payAccountGroup.getMemberCanTransfer() || StringTools.isBlank(payAccountGroup.getMemberTransferConfig())) {
                        apiResp.getBody().setTransferState(2);
                    }else{
                        CashWithdrawalConfig config = JsonTools.fromJson(payAccountGroup.getMemberTransferConfig(),CashWithdrawalConfig.class);
                        boolean flag = true;
                        String weekNames = "";
                        if (config.getMonthStartDay() != null && config.getMonthEndDay() != null) {
                            int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
                            if (day < config.getMonthStartDay() || day > config.getMonthEndDay()) {
                                flag = false;
                            }
                        }

                        if (flag && StringUtils.isNotBlank(config.getCashWithdrawalWeeks())) {
                            int week = DateTools.getWeek(new Date());
                            String[] names = config.getCashWithdrawalWeeks().split(",");
                            for (String name : names) {
                                if (week == DefaultEnum.Weeks.valueOf(name).index()) {
                                    if (StringUtils.isNotBlank(config.getCashWithdrawalTimes())) {
                                        String[] times = config.getCashWithdrawalTimes().split(" - ");
                                        if (times.length == 2) {
                                            Date currentDate = new Date();
                                            try {
                                                String dateStr = DateFormatUtils.format(currentDate, "yyyy-MM-dd");
                                                String startStr = dateStr + " " + times[0];
                                                Date startDate = DateUtils.parseDate(startStr, "yyyy-MM-dd HH:mm:ss");
                                                String endStr = dateStr + " " + times[1];
                                                Date endDate = DateUtils.parseDate(endStr, "yyyy-MM-dd HH:mm:ss");

                                                if (startDate.before(currentDate) && endDate.after(currentDate)) {
                                                    flag = true;
                                                }
                                            } catch (ParseException e) {
                                                log.error(e.getMessage(), e);
                                            }
                                        }
                                    }
                                }
                                weekNames = weekNames + "," + DefaultEnum.Weeks.valueOf(name).note();
                            }
                            weekNames = weekNames.substring(1);
                        }

                        if (!flag) {
                            apiResp.getBody().setTransferState(3);
                        }

                        apiResp.getBody().setTransferDayStr("每月" + config.getMonthStartDay() + "号-" + config.getMonthEndDay() + "号");
                        apiResp.getBody().setTransferTimeStr("每" + weekNames + "的" + config.getCashWithdrawalTimes() + "提现");
                    }
                }
            }
        }
        return apiResp;
    }

    /**
     * 充值
     * @param request
     * @return
     */
    @Route(value = { "/xcx/v1/member/wallet/recharge.do" }, method = "POST")
    public MemberWalletRechargeResponse recharge(HttpServletRequest request) {
        MemberWalletRechargeResponse apiResp = new MemberWalletRechargeResponse(ClientAPICodeConstants.EXECUTE_ERROR, "充值失败，请稍后再试");
        try {
            MemberWalletRechargeRequest apiReq = WebUtils.getJsonRequest(request, MemberWalletRechargeRequest.class);
            if (apiReq != null && apiReq.getBody().getMemberId() != null && apiReq.getBody().getMoney() != null) {
                Integer payType = apiReq.getBody().getPayType() == null ? EPayType.WXPay.index() : apiReq.getBody().getPayType();

                if (EPayType.WXPay.index().equals(payType) || EPayType.Alipay.index().equals(payType)) {
                    if (StringTools.isBlank(apiReq.getBody().getAppId())) {
                        apiResp.setMsg("无效的应用ID");
                        return apiResp;
                    }
                }
                
                LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
                if (!member.getId().equals(apiReq.getBody().getMemberId())) {
                    apiResp.setMsg("你是谁？");
                    return apiResp;
                }

                if (apiReq.getBody().getMoney() <= 0 || apiReq.getBody().getMoney() > 999) {
                    apiResp.setMsg("请选择充值金额");
                    return apiResp;
                }

                MemberWallet wallet = MemberWalletService.self().getByMemberId(member.getId());
                if (wallet == null) {
                    apiResp.setCode(ClientAPICodeConstants.NOT_FIND, "未找到钱包信息");
                    return apiResp;
                }

                if (EPayType.WXPay.index().equals(payType)) {
                    WXPayNormalPayService payService = PayServiceFactory.self().getWXPayNormalPayService(apiReq.getBody().getAppId()
                            ,EBusinessType.RECHARGE.index());
                    if (payService == null) {
                        apiResp.setMsg("未配置应用微信支付服务");
                        return apiResp;
                    }

                    OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE,MicroConstants.PROGRAM_TYPE_NAME);
                    operateInfo.setOperator(EOperatorType.Member.index(),member.getFullName());

                    CacheOrderCollect orderCollect = OrderCollectManager.buildMemberRechargeOrderCollect(member, apiReq.getBody().getMoney(), payService.getConfig(), operateInfo);
                    if (orderCollect == null) {
                        apiResp.setMsg("创建订单失败，请稍后再试");
                        return apiResp;
                    }

                    WXPayNormalPayResponse externalResult = payService.applyPayOrder(orderCollect.getPayOrder());
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getPrepay_id())){
                            String payInfo = payService.buildXCXData(externalResult.getPrepay_id());
                            if(StringTools.isNotBlank(payInfo)){
                                OrderCollectManager.saveWXPayOrderExternalContent(orderCollect.getPayOrder().getTradeNo(), JsonTools.toJson(externalResult));
                                log.info("微信支付返回：" + payInfo);
                                apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                                apiResp.getBody().setTradeNo(orderCollect.getPayOrder().getTradeNo());
                                apiResp.getBody().setPayType(payType);
                                apiResp.getBody().setPayInfo(payInfo);
                            }
                        } else {
                            log.error("微信支付返回错误，返回信息：{{0:json}}", externalResult);
                        }
                    } else {
                        log.error("微信支付无返回，订单信息：{{0:json}}", orderCollect);
                    }
                }else if(EPayType.Alipay.index().equals(payType)) {
                	AlipayNormalPayService payService = PayServiceFactory.self().getAlipayNormalPayService(apiReq.getBody().getAppId(),
                            EBusinessType.RECHARGE.index());
                    if (payService == null) {
                        apiResp.setMsg("未配置应用支付宝支付服务");
                        return apiResp;
                    }
                    
                    OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE, MicroConstants.PROGRAM_TYPE_NAME);
                    operateInfo.setOperator(EOperatorType.Member.index(), member.getFullName());

                    CacheOrderCollect orderCollect = OrderCollectManager.buildMemberRechargeOrderCollect(member,apiReq.getBody().getMoney(), payService.getConfig(), operateInfo);
                    if (orderCollect == null) {
                        apiResp.setMsg("创建订单失败，请稍后再试");
                        return apiResp;
                    }
                    
                    AlipayTradeCreateResponse externalResult = payService.applyPayOrder(orderCollect.getAlipayOrder());
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getOutTradeNo())) {
                        	OrderCollectManager.saveAlipayOrderExternalContent(orderCollect.getAlipayOrder().getTradeNo(), JsonTools.toJson(externalResult));
                            apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                            apiResp.getBody().setTradeNo(externalResult.getTradeNo());
                            apiResp.getBody().setPayType(payType);
                        }else {
                            log.error("支付宝支付返回错误，返回信息：{{0:json}}", externalResult);
                        }
                    } else {
                        log.error("支付宝支付无返回，订单信息：{{0:json}}", orderCollect);
                    }
                }else {
                	 apiResp.setMsg("无效的支付类型");
                     return apiResp;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return apiResp;
    }

    @Route(value = {"/xcx/v1/member/wallet/recharge/result.do"}, method = "POST")
    public MemberWalletRechargeResultResponse rechargeResult(HttpServletRequest request){
    	MemberWalletRechargeResultResponse apiResp = new MemberWalletRechargeResultResponse(ClientAPICodeConstants.NULL_DATA, "未找到支付结果");
        try {
        	MemberWalletRechargeResultRequest apiReq = WebUtils.getJsonRequest(request, MemberWalletRechargeResultRequest.class);
            if (apiReq != null && apiReq.getBody().getPayType() != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo())) {
                if(EPayType.WXPay.index().equals(apiReq.getBody().getPayType())){
                    Date createDate = new Date();
                    WXPayOrder payOrder = WXPayOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                    if (payOrder != null) {
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                        apiResp.getBody().setResultCode(PayResultCode.WAIT);
                        if (EPayState.Success.index().equals(payOrder.getPayStatus())) {
                        	MemberRechargeOrder rechargeOrder = MemberRechargeOrderService.self(new Date()).getByTradeNo(payOrder.getBusinessTradeNo());
                            if (rechargeOrder != null) {
                                if (MemberRechargeOrderEnum.State.Success.index().equals(rechargeOrder.getState())) {
                                    apiResp.getBody().setResultCode(PayResultCode.SUCCESS);
                                }else if(MemberRechargeOrderEnum.State.Fail.index().equals(rechargeOrder.getState())){
                                    apiResp.getBody().setResultCode(PayResultCode.FAIL);
                                }
                            } else {
                                log.error("未找到充值订单，支付订单号：{{0}}，业务订单号：{{1}}", payOrder.getTradeNo(), payOrder.getBusinessTradeNo());
                            }
                        }
                    }
                }else if(EPayType.Alipay.index().equals(apiReq.getBody().getPayType())){
                    Date createDate = new Date();
                    AlipayOrder payOrder = AlipayOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                    if (payOrder != null) {
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                        apiResp.getBody().setResultCode(PayResultCode.WAIT);
                        if (EPayState.Success.index().equals(payOrder.getPayStatus())) {
                        	MemberRechargeOrder rechargeOrder = MemberRechargeOrderService.self(new Date()).getByTradeNo(payOrder.getBusinessTradeNo());
                            if (rechargeOrder != null) {
                                if (MemberRechargeOrderEnum.State.Success.index().equals(rechargeOrder.getState())) {
                                    apiResp.getBody().setResultCode(PayResultCode.SUCCESS);
                                }else if(MemberRechargeOrderEnum.State.Fail.index().equals(rechargeOrder.getState())){
                                    apiResp.getBody().setResultCode(PayResultCode.FAIL);
                                }
                            } else {
                                log.error("未找到充值订单，支付订单号：{{0}}，业务订单号：{{1}}", payOrder.getTradeNo(), payOrder.getBusinessTradeNo());
                            }
                        }
                    }
                }else {
	               	 apiResp.setMsg("无效的支付类型");
	                 return apiResp;
	            }
            }
        } catch (Exception e) {
            log.error("获取订单结果失败，" + e.getMessage(), e);
        }
        return apiResp;
    }
    
    @Route(value = "/xcx/v1/member/wallet/transfer_money/apply.do", method = "POST")
    public DefaultAPIResponse apply(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "提现失败");
        MemberTransferMoneyApplyRequest apiReq = WebUtils.getJsonRequest(request, MemberTransferMoneyApplyRequest.class);
        LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
        if (member != null && apiReq != null && apiReq.getBody().getPrice() != null) {
            OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE,MicroConstants.PROGRAM_TYPE_NAME);
            operateInfo.setOperator(EOperatorType.Member.index(),member.getFullName());

            Integer money = NumberTools.changeMoney(apiReq.getBody().getPrice());

            try {
                if(MemberTransferMoneyOrderService.self().apply(member.getId(),money,operateInfo)){
                    apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                }
            } catch (LogicException e) {
                apiResp.setMsg(e.getMessage());
            }
        }
        return apiResp;
    }

    @Route(value = "/xcx/v1/member/wallet/transfer_money/order/list.data", method = "POST")
    public MemberTransferMoneyOrderListResponse transferMoneyOrderList(HttpServletRequest request) {
        MemberTransferMoneyOrderListResponse apiResp = new MemberTransferMoneyOrderListResponse(ClientAPICodeConstants.EXECUTE_ERROR, "提现失败");
        MemberTransferMoneyOrderListRequest apiReq = WebUtils.getJsonRequest(request, MemberTransferMoneyOrderListRequest.class);
        LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
        if (member != null && apiReq != null) {
            Integer pageNo = apiReq.getBody().getPageNo() == null ? 1 : apiReq.getBody().getPageNo();
            MemberTransferMoneyOrderSearch search = new MemberTransferMoneyOrderSearch();
            search.setMemberId(member.getId());
            search.setState(apiReq.getBody().getState());
            List<MemberTransferMoneyOrder> transferMoneyOrderList = MemberTransferMoneyOrderService.self().findBySearch(search, pageNo, MicroConstants.PAGE_LIMIT);
            if (transferMoneyOrderList != null && transferMoneyOrderList != null) {
                apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                apiResp.getBody().setItems(new ArrayList<>());
                for(MemberTransferMoneyOrder transferMoneyOrder : transferMoneyOrderList){
                    MemberTransferMoneyOrderListResponse.Item item = new MemberTransferMoneyOrderListResponse.Item();
                    item.setTradeNo(transferMoneyOrder.getTradeNo());
                    item.setMoneyStr(transferMoneyOrder.getMoneyStr());
                    item.setState(transferMoneyOrder.getState());
                    item.setStateName(transferMoneyOrder.getStateName());
                    item.setRejectNote(transferMoneyOrder.getRejectNote());
                    item.setCreateDate(transferMoneyOrder.getCreateDate());
                    apiResp.getBody().getItems().add(item);
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/xcx/v1/member/wallet/transfer_money/order/info.data", method = "POST")
    public MemberTransferMoneyOrderInfoResponse transferMoneyOrderInfo(HttpServletRequest request) {
        MemberTransferMoneyOrderInfoResponse apiResp = new MemberTransferMoneyOrderInfoResponse(ClientAPICodeConstants.EXECUTE_ERROR, "提现失败");
        MemberTransferMoneyOrderInfoRequest apiReq = WebUtils.getJsonRequest(request, MemberTransferMoneyOrderInfoRequest.class);
        LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
        if (member != null && apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo())) {
            MemberTransferMoneyOrder transferMoneyOrder = MemberTransferMoneyOrderService.self().getByTradeNo(apiReq.getBody().getTradeNo());
            if (transferMoneyOrder != null) {
                apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                apiResp.getBody().setTradeNo(transferMoneyOrder.getTradeNo());
                apiResp.getBody().setProfitProportion(transferMoneyOrder.getProfitProportion());
                apiResp.getBody().setMoneyStr(transferMoneyOrder.getMoneyStr());
                apiResp.getBody().setReceiptMoneyStr(transferMoneyOrder.getReceiptMoneyStr());
                apiResp.getBody().setState(transferMoneyOrder.getState());
                apiResp.getBody().setStateName(transferMoneyOrder.getStateName());
                apiResp.getBody().setRejectNote(transferMoneyOrder.getRejectNote());
                apiResp.getBody().setHandleType(transferMoneyOrder.getHandleType());
                apiResp.getBody().setHandleTypeName(transferMoneyOrder.getHandleTypeName());
                apiResp.getBody().setHandleDate(transferMoneyOrder.getHandleDate());
                apiResp.getBody().setCreateDate(transferMoneyOrder.getCreateDate());
            }
        }
        return apiResp;
    }
}
